package studio.baka.satoripixeldungeon.effects;

import studio.baka.satoripixeldungeon.scenes.GameScene;
import studio.baka.satoripixeldungeon.scenes.PixelScene;
import studio.baka.satoripixeldungeon.tiles.DungeonTilemap;
import studio.baka.satoripixeldungeon.ui.RenderedTextBlock;
import com.watabou.noosa.Camera;
import com.watabou.noosa.Game;
import com.watabou.noosa.RenderedText;
import com.watabou.utils.SparseArray;

import java.util.ArrayList;

public class FloatingText extends RenderedTextBlock {

    private static final float LIFESPAN = 1f;
    private static final float DISTANCE = DungeonTilemap.SIZE;

    private float timeLeft;

    private int key = -1;

    private static final SparseArray<ArrayList<FloatingText>> stacks = new SparseArray<>();

    public FloatingText() {
        super(9 * PixelScene.defaultZoom);
        setHightlighting(false);
    }

    @Override
    public void update() {
        super.update();

        if (timeLeft > 0) {
            if ((timeLeft -= Game.elapsed) <= 0) {
                kill();
            } else {
                float p = timeLeft / LIFESPAN;
                alpha(p > 0.5f ? 1 : p * 2);

                float yMove = (DISTANCE / LIFESPAN) * Game.elapsed;
                y -= yMove;
                for (RenderedText t : words) {
                    t.y -= yMove;
                }
            }
        }
    }

    @Override
    public void kill() {
        if (key != -1) {
            synchronized (stacks) {
                stacks.get(key).remove(this);
            }
            key = -1;
        }
        super.kill();
    }

    @Override
    public void destroy() {
        kill();
        super.destroy();
    }

    public void reset(float x, float y, String text, int color) {

        revive();

        zoom(1 / (float) PixelScene.defaultZoom);

        text(text);
        hardlight(color);

        setPos(
                PixelScene.align(Camera.main, x - width() / 2),
                PixelScene.align(Camera.main, y - height())
        );

        timeLeft = LIFESPAN;
    }

    /* STATIC METHODS */

    public static void show(float x, float y, String text, int color) {
        Game.runOnRenderThread(() -> {
            FloatingText txt = GameScene.status();
            if (txt != null) {
                txt.reset(x, y, text, color);
            }
        });
    }

    public static void show(float x, float y, int key, String text, int color) {
        Game.runOnRenderThread(() -> {
            FloatingText txt = GameScene.status();
            if (txt != null) {
                txt.reset(x, y, text, color);
                push(txt, key);
            }
        });
    }

    private static void push(FloatingText txt, int key) {

        synchronized (stacks) {
            txt.key = key;

            ArrayList<FloatingText> stack = stacks.get(key);
            if (stack == null) {
                stack = new ArrayList<>();
                stacks.put(key, stack);
            }

            if (stack.size() > 0) {
                FloatingText below = txt;
                int aboveIndex = stack.size() - 1;
                while (aboveIndex >= 0) {
                    FloatingText above = stack.get(aboveIndex);
                    if (above.bottom() + 4 > below.top()) {
                        above.setPos(above.left(), below.top() - above.height() - 4);

                        below = above;
                        aboveIndex--;
                    } else {
                        break;
                    }
                }
            }

            stack.add(txt);
        }
    }
}
